// $Id: sizes.cpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <xpcom/array.hpp>
#include <xpcom/ptr_array.hpp>
#include <xpcom/uuid.hpp>
#include "def.hpp"
#include "interface_def.hpp"

BOOST_AUTO_TEST_CASE_TEMPLATE(test_size_empty_clear, T, test_types)
{
    using namespace xpcom;
    typedef array<T> Array;

    Array a1;
    BOOST_CHECK(a1.empty());
    BOOST_CHECK_EQUAL(a1.size(), 0);
    BOOST_CHECK(a1.capacity() >= 0);

    Array a2(8);
    BOOST_CHECK(!a2.empty());
    BOOST_CHECK_EQUAL(a2.size(), 8);
    BOOST_CHECK(a2.capacity() >= 8);

    Array a3(0);
    BOOST_CHECK(a3.empty());
    BOOST_CHECK_EQUAL(a3.size(), 0);
    BOOST_CHECK(a3.capacity() >= 0);

    a1.clear();
    BOOST_CHECK(a1.empty());
    a2.clear();
    BOOST_CHECK(a2.empty());
    a3.resize(90);
    a3.clear();
    BOOST_CHECK(a3.empty());
}

BOOST_AUTO_TEST_CASE(test_size_empty_clear_ptr)
{
    using namespace xpcom;
    typedef ptr_array<IBase> Array;

    X_count_guard g;
    X_count(0);

    Array a1;
    BOOST_CHECK(a1.empty());
    BOOST_CHECK_EQUAL(a1.size(), 0);
    BOOST_CHECK(a1.capacity() >= 0);

    Array a2(8);
    BOOST_CHECK(!a2.empty());
    BOOST_CHECK_EQUAL(a2.size(), 8);
    BOOST_CHECK(a2.capacity() >= 8);

    Array a3(0);
    BOOST_CHECK(a3.empty());
    BOOST_CHECK_EQUAL(a3.size(), 0);
    BOOST_CHECK(a3.capacity() >= 0);

    a1.clear();
    BOOST_CHECK(a1.empty());
    a2.clear();
    BOOST_CHECK(a2.empty());
    a3.resize(90);
    a3.clear();
    BOOST_CHECK(a3.empty());

    BOOST_CHECK_EQUAL(X_count(), 0);
}

BOOST_AUTO_TEST_CASE_TEMPLATE(test_max_size, T, test_types)
{
    using namespace xpcom;
    typedef array<T> Array;

    Array a1;
    BOOST_CHECK_EQUAL(a1.max_size(),
            (static_cast<typename Array::size_type>(-1) / sizeof(typename Array::element_type)) - 1);
}

BOOST_AUTO_TEST_CASE(test_max_size_ptr)
{
    using namespace xpcom;
    typedef ptr_array<ID> Array;

    Array a1;
    BOOST_CHECK_EQUAL(a1.max_size(),
            (static_cast<Array::size_type>(-1) / sizeof(Array::element_type)) - 1);
}

BOOST_AUTO_TEST_CASE_TEMPLATE(test_reserve_capacity, T, test_types)
{
    using namespace xpcom;
    typedef array<T> Array;

#ifdef XPCOM_ENABLE_LENGTH_IS
    Array a1(8);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= 8);

    a1.reserve(18);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= 18);

    a1.reserve(3);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= 8);
#else
    Array a1(8);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= a1.size());

    a1.reserve(18);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= a1.size());

    a1.reserve(3);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= a1.size());
#endif
}

BOOST_AUTO_TEST_CASE(test_reserve_capacity_ptr)
{
    using namespace xpcom;
    typedef ptr_array<IC> Array;

#ifdef XPCOM_ENABLE_LENGTH_IS
    Array a1(8);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= 8);

    a1.reserve(18);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= 18);

    a1.reserve(3);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= 8);
#else
    Array a1(8);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= a1.size());

    a1.reserve(18);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= a1.size());

    a1.reserve(3);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= a1.size());
#endif
}

BOOST_AUTO_TEST_CASE_TEMPLATE(test_resize, T, test_types)
{
    using namespace xpcom;
    typedef array<T> Array;

    Array a1;
    BOOST_CHECK(a1.empty());
    BOOST_CHECK_EQUAL(a1.size(), 0);
    BOOST_CHECK(a1.capacity() >= a1.size());

    a1.resize(8);
    BOOST_CHECK_EQUAL(a1.size(), 8);
    BOOST_CHECK(a1.capacity() >= a1.size());

    a1.resize(2);
    BOOST_CHECK_EQUAL(a1.size(), 2);
    BOOST_CHECK(a1.capacity() >= a1.size());
}

BOOST_AUTO_TEST_CASE(test_resize_A)
{
    using namespace xpcom;
    typedef array<A> Array;

    A_count_guard g;
    A::count = 0;
    {
        Array a1(2);
        BOOST_CHECK_EQUAL(a1.size(), 2);
        BOOST_CHECK(a1.capacity() >= a1.size());
        BOOST_CHECK_EQUAL(A::count, 2);

        a1.resize(8);
        BOOST_CHECK_EQUAL(a1.size(), 8);
        BOOST_CHECK(a1.capacity() >= a1.size());
        BOOST_CHECK_EQUAL(A::count, 8);
        for (int i = 0; i < 8; i++) {
            a1[i].n = i;
        }

        a1.resize(3);
        BOOST_CHECK_EQUAL(a1.size(), 3);
        BOOST_CHECK(a1.capacity() >= a1.size());
        BOOST_CHECK_EQUAL(A::count, 3);

        for (int i = 0; i < 3; i++) {
            BOOST_CHECK_EQUAL(a1[i].n, i);
        }
    }
    BOOST_CHECK_EQUAL(A::count, 0);
}

BOOST_AUTO_TEST_CASE(test_resize_ptr)
{
    using namespace xpcom;
    typedef ptr_array<IBase> Array;

    X_count_guard g;
    X_count(0);
    {
        Array a1(2);
        BOOST_CHECK_EQUAL(a1.size(), 2);
        BOOST_CHECK(a1.capacity() >= a1.size());
        for (Array::size_type i = 0; i < a1.size(); ++i) {
            a1[i].reset(X_make_instance());
        }
        BOOST_CHECK_EQUAL(X_count(), 2);

        a1.resize(8);
        BOOST_CHECK_EQUAL(a1.size(), 8);
        BOOST_CHECK(a1.capacity() >= a1.size());
        for (Array::size_type i = 0; i < a1.size(); ++i) {
            a1[i].reset(X_make_instance());
        }
        BOOST_CHECK_EQUAL(X_count(), 8);
        for (int i = 0; i < 8; i++) {
            a1[i]->setN(i);
        }

        a1.resize(3);
        BOOST_CHECK_EQUAL(a1.size(), 3);
        BOOST_CHECK(a1.capacity() >= a1.size());
        BOOST_CHECK_EQUAL(X_count(), 3);

        for (int i = 0; i < 3; i++) {
            BOOST_CHECK_EQUAL(a1[i]->getN(), i);
        }
    }
    BOOST_CHECK_EQUAL(X_count(), 0);
}
